/**************************************************************************
 * @doc CONFIGURATION
 * @module ztexpr.c |  
 * Source code for loading the individual configuration parameters from 
 * config.sys into the data files
 *
 * Product     :   SoftPay 2000 (Global Payment Methodology).
 * <nl>Developer   :   
 * <nl>Notes       :
 *
 * @head3 Zontalk configuration Functions |
 * @index | index_name
 * @end
 *
 * Copyright (c) 1996-2000 by VeriFone Inc. All rights reserved.
 * 
 * No part of this software may be used, stored, compiled, reproduced,
 * modified, transcribed, translated, transmitted, or transferred, in any form 
 * or by any means whether electronic, mechanical, magnetic, optical, 
 * or otherwise, without the express prior written permission of VeriFone, Inc.
 *
 * Revision History
 * ------------------------------------------------------------------------
$Log:  $
 * ------------------------------------------------------------------------
 ********************************************************************************/

#include <project.h>

#ifdef ZTEXPRESS_DEFINED

#define VSTZEXPR_C

#include <aclconio.h>
#include <acldev.h>
#include <stdio.h>
#include <string.h>
#include <acdce.h>
#include <errno.h>
#include <applidl.h>

/** /#define DEBUG_VSZTEXPR*/
#ifdef DEBUG_VSZTEXPR
#define DEBUG_95
#endif

#include <define.h>
#include <spdebug.h>
#include <cfg.h>
#include <hdt.h>
#include <pct.h>
#include <tct.h>
#include <validt.h>
#include <msgfuncs.h>
#include <msg.h>
#include <ui.h>
#include <scalls.h>
#include <mem.h>
#include <table.h>      /* For inGetFunctionPointer() prototype */
#include <transact.h>
#include <confio.h>
#include <ztconf.h>

#include <gds.h>
#include <util.h>

#define CFG_VAR_SIZE (50)

static int inLdExprCfgVars(CFG_REC* psrCFG,char* szCfgVal);

#define LOBYTE  0
#define HIBYTE  1

#define LOBYTE2 2
#define HIBYTE2 3

/********************************************************************************************* 
* @func int | inGetExprCfg | 
*     Updates the configuration records based on config.sys values
*
* @rdesc return values.
* @flag int |  VS_ERR or VS_SUCCESS
* @end
**********************************************************************************************/

int inGetExprCfg() {
    CFG_REC srCFG;

    char szInputBuffer[CFG_VAR_SIZE + 1];
    char stVerInfo[GEN_VER_SIZE];
    char szTodaysDate[COMPLETE_DATE_AND_TIME_SIZE + 1];

    int inBytesRead = 0;
    int hConfFHandle = 0;
    int inResult = 0;

    memset((char *) &srCFG, NULL_CH, sizeof(srCFG));

    hConfFHandle = open("F:cfg.dat", O_RDONLY);

    if (hConfFHandle < 0) {
        /** /pdebug(("Could not open file"));*/
        return(VS_ERR);
    }

    if (read(hConfFHandle, stVerInfo, GEN_VER_SIZE) != GEN_VER_SIZE) {
        close(hConfFHandle);
        return(VS_ERR);
    }

    inBytesRead = SVC_CLOCK(GET_CLOCK, szTodaysDate, COMPLETE_DATE_AND_TIME_SIZE);
    szTodaysDate[inBytesRead] = 0;
    pdebug(("Start: %s", szTodaysDate));

    inResult = read(hConfFHandle, (char *) &srCFG, SIZE_CFG_REC);
    while (inResult > 0) {
        /** / pdebug((srCFG.szCFGKey)); */
        if ((inResult = get_env(srCFG.szCFGKey, szInputBuffer, CFG_VAR_SIZE)) > 0) {
            szInputBuffer[(sizeof(szInputBuffer) - 1)] = NULL_CH;
            if (inResult < sizeof(szInputBuffer))
                szInputBuffer[inResult] = NULL_CH;

            if (inLdExprCfgVars(&srCFG, szInputBuffer)) {
                close(hConfFHandle);
                return(VS_ERR);
            }

            /*
             *  now, remove the value from the env
             */

            /*
                     * Do not delete express config variables for VeriCenter to monitor.
                     
                     if (put_env(srCFG.szCFGKey, "", 0) != VS_SUCCESS)
                     {
                         close(hConfFHandle);
                         return(VS_ERR);
                     }
                     */
        }

        inResult = read(hConfFHandle, (char *) &srCFG, SIZE_CFG_REC);
    }

    vdGetIdlePrompt();

    put_env("#CZE", "0", 1);  // Reset the CZE parameter to 0. 

    /*
    * Do not delete CZE variable for VeriCenter purpose.
        
    if (put_env("#CZE", "", 0) != VS_SUCCESS)
    {
        close(hConfFHandle);
        return(VS_ERR);
    }
    */       

    inBytesRead = SVC_CLOCK(GET_CLOCK, szTodaysDate, COMPLETE_DATE_AND_TIME_SIZE);
    szTodaysDate[inBytesRead] = 0;
    pdebug(("Stop: %s", szTodaysDate));

    if (close(hConfFHandle) < 0) {
        /** /pdebug(("close hConfFHandle"));*/
        return(VS_ERR);
    }       

    return(VS_SUCCESS);
}

/********************************************************************************************* 
* @func int | inLdExprCfgVars | 
*       Reads the fielddef file to determine the offset
*        to-be-updated within the config rec.
*
* @parm CFG_REC * | psrCFG | 
*       Record containing information about the variable 
*
* @parm char * | szCfgVal | 
*       Value to be added to the data file
*
* @rdesc return values.
* @flag int    |  VS_ERR / VS_SUCCESS
* @end
**********************************************************************************************/

static int inLdExprCfgVars(CFG_REC* psrCFG,char* szCfgVal) {
    FieldDefinition srFld;
    char stVerInfo[GEN_VER_SIZE];
    char szFileName[FILENAME_SIZE + 1];
    char szFmt[8 + 1];
    char szCnv[3 + 1];
    char szDispMsg[MESSAGE_SIZE + 1];

    int i,
    hDataFile,
    hFieldDescriptionFile;

    unsigned char ucTargetType = ' ';
    unsigned char uchTemp = ' ';
    char chTemp = ' ';
    char* pchRdBuf = (char*) 0;

    int inVarSize;
    int inIncrSize;

    int inOffset = 0;
    int inTargetSize = 0;
    int inTestVal = 0;
    int inRecSize = 0;
    int inResult = 0;
    int inBitCnt = 0;
    int inStartBits = 0;
    int inTotFields = psrCFG->inFldNum;
    int inTotFldCnt = 0;

    int inTemp = 0;
    long lnTemp = 0L;

    unsigned char ucNewVal = (unsigned char) 0;
    unsigned char ucOldVal = (unsigned char) 0;
    short shTargetValidationIdx = NO_VALIDATION;
    int inFieldID;
    PFI_PSZ pinValFunction;

    /*
     *  Open the .fld file
     *  "VS%s.FLD"   
     */
    strcpy(szFmt, "F:%s.FLD");
    sprintf(szFileName, szFmt, psrCFG->szTblName);
    /** /pdebug(("szFmt<%s>",szFmt));*/
    /** /pdebug(("szFileName<%s>",szFileName));*/

    if ((hFieldDescriptionFile = open(szFileName, O_RDONLY)) != -1) {
        if (read(hFieldDescriptionFile, stVerInfo, GEN_VER_SIZE) != GEN_VER_SIZE) {
            close(hFieldDescriptionFile);
            /** /pdebug(("Bad read ver fld"));*/
            return(VS_ERR);
        }

        memset((char *) &srFld, NULL_CH, sizeof(srFld));
        inResult = read(hFieldDescriptionFile, (char *) &srFld, sizeof(FieldDefinition));

        while (inResult > 0) {
            /** /pdebug(("rfld cnt<%d>",inResult)); 15 bytes */

            inVarSize = 0;

            switch (srFld.ucFieldType) {
            case FLD_CHAR:
                 {
                    /** /pdebug(("FLD_CHAR"));*/
                    inVarSize = CHAR_SIZE;
                    inRecSize += inVarSize;
                    if (psrCFG->inFldNum > 1)
                        inOffset += inVarSize;
                    break;
                }   

            case FLD_SHORT:
                 {
                    /** /pdebug(("FLD_SHORT"));*/
                    if (inRecSize % 2 == 1) {
                        if (psrCFG->inFldNum > 0)
                            inOffset++;
                        inRecSize++;
                    }                        
                    inVarSize = SHORT_SIZE;
                    inRecSize += inVarSize;
                    if (psrCFG->inFldNum > 1)
                        inOffset += inVarSize;
                    break;
                }  

            case FLD_INT:
                 {
                    /** /pdebug(("FLD_INT"));*/
                    if (inRecSize % 2 == 1) {
                        if (psrCFG->inFldNum > 0)
                            inOffset++;
                        inRecSize++;
                    }                        
                    inVarSize = INT_SIZE;
                    inRecSize += inVarSize;
                    if (psrCFG->inFldNum > 1)
                        inOffset += inVarSize;                   
                    break;
                }              

            case FLD_LONG:
                 {
                    /** /pdebug(("FLD_LONG"));*/
                    if (inRecSize % 2 == 1) {
                        if (psrCFG->inFldNum > 0)
                            inOffset++;
                        inRecSize++;
                    }                        
                    inVarSize = LONG_SIZE;
                    inRecSize += inVarSize;
                    if (psrCFG->inFldNum > 1)
                        inOffset += inVarSize;
                    break;
                }   

            case FLD_STR:
                 {
                    /** /pdebug(("FLD_STR"));*/
                    inVarSize = (srFld.inFieldSize + 1);
                    inRecSize += inVarSize;
                    if (psrCFG->inFldNum > 1)
                        inOffset += inVarSize;
                    break;
                }   

            case FLD_BYTE:
                 {
                    /** /pdebug(("FLD_BYTE"));*/
                    inVarSize = BYTE_SIZE;
                    inRecSize += inVarSize;
                    if (psrCFG->inFldNum > 1)
                        inOffset += inVarSize;
                    break;
                }

            case FLD_BIT:
                 {
                    if (inRecSize % 2 == 1 && inBitCnt == 0) {
                        if (psrCFG->inFldNum > 0)
                            inOffset++;
                        inRecSize++;
                    }                        
                    if (inBitCnt > 63)
                        return(VS_ERR);

                    if (!inStartBits)
                        inStartBits = (inTotFldCnt + 1);

                    if (inBitCnt == 0 || inBitCnt == 16 || inBitCnt == 32 || inBitCnt == 48)
                        inRecSize += SHORT_SIZE;

                    inVarSize = INT_SIZE; /* always the case... */

                    inIncrSize = 0;

                    if (inBitCnt == 8 || inBitCnt == 16 || inBitCnt == 24 || inBitCnt == 32 || inBitCnt == 40 || inBitCnt == 48 || inBitCnt == 56 || inBitCnt == 64)
                        inIncrSize = (BYTE_SIZE);

                    inBitCnt++;

                    if (psrCFG->inFldNum >= 1)
                        inOffset += inIncrSize;                     

                    break;
                }   

            case FLD_NULL:
                 {
                    /* EOF */
                    inResult = 0;
                    continue;
                }   

            default:
                 {
                    close(hFieldDescriptionFile);
                    return(VS_ERR);
                }
            } /* end switch (srFld.ucFieldType) */

            if (psrCFG->inFldNum > 0) {
                inTargetSize = inVarSize;
                ucTargetType = srFld.ucFieldType;
                shTargetValidationIdx = srFld.shFieldFuncID;
            }

            psrCFG->inFldNum--;
            inTotFldCnt++;          

            inResult = read(hFieldDescriptionFile, (char *) &srFld, sizeof(FieldDefinition));
        }

        close(hFieldDescriptionFile);
        if (inRecSize % 2 == 1)
            inRecSize++;                        

        /* Run the Validation function before loading */

        /**/ pdebug(("ValIdx=%d", shTargetValidationIdx)); /**/

        if (shTargetValidationIdx != NO_VALIDATION) {
            inFieldID = (int) shTargetValidationIdx;
            if ((pinValFunction = inGetFunctionPointer(inFieldID)) == NULL_PFI)
                inResult = VS_ERR;
            else
                inResult = pinValFunction(szCfgVal);

            if (inResult == VS_ERR) {
                clrscr();
                strcpy(szDispMsg, "LABEL - ");
                strcat(szDispMsg, psrCFG->szCFGKey);            
                vdDisplayAt(obDisp.inHomeCol, obDisp.inInputLine, szDispMsg, CLR_EOL);

                vdDisplayMessageFromFile(lnGGErrorMessage(), ERROR_MSG);
                return(VS_ERR);
            }
        }


        /*
         *  Open the .dat file
         *  "%s.DAT"     
         */
        strcpy(szFmt, "%s.DAT");
        sprintf(szFileName, szFmt, psrCFG->szTblName);

        if ((hDataFile = open(szFileName, O_RDWR)) != -1) {
            if (read(hDataFile, stVerInfo, GEN_VER_SIZE) != GEN_VER_SIZE) {
                close(hDataFile);
                /** /pdebug(("read ver"));*/
                return(VS_ERR);
            }

            pchRdBuf = pchAlloc(inRecSize);
            if (!pchRdBuf) {
                close(hDataFile);
                /** /pdebug(("alloc"));*/
                return(VS_ERR);
            }

            for (i = 0; i < psrCFG->inRecNum; i++) {
                if (read(hDataFile, pchRdBuf, inRecSize) != inRecSize) {
                    /** /pdebug(("read rec"));*/
                    vdFree(pchRdBuf);
                    close(hDataFile);
                    return(VS_ERR);
                }
            }

            strcpy(szCnv, "%d");                

            switch (ucTargetType) {
            case FLD_CHAR:
                 {
                    szCfgVal[1] = NULL_CH;
                    strcpy(szCnv, "%c");                
                    sscanf(szCfgVal, szCnv, &uchTemp);
                    pchRdBuf[inOffset] = uchTemp; 
                    break;
                }

            case FLD_SHORT:
                 {
                    union {
                        short shVar;
                        unsigned char shVars[2];
                    } shUn;

                    szCfgVal[6] = NULL_CH;
                    sscanf(szCfgVal, szCnv, &inTemp);
                    shUn.shVar = (short) inTemp;                    
                    pchRdBuf[inOffset] = shUn.shVars[LOBYTE]; 
                    pchRdBuf[inOffset + 1] = shUn.shVars[HIBYTE];
                    break;
                }

            case FLD_INT:
                 {
                    union {
                        int iVar;
                        unsigned char iVars[2];
                    } intUn;

                    szCfgVal[6] = NULL_CH;
                    sscanf(szCfgVal, szCnv, &inTemp);
                    intUn.iVar = inTemp;                    
                    pchRdBuf[inOffset] = intUn.iVars[LOBYTE]; 
                    pchRdBuf[inOffset + 1] = intUn.iVars[HIBYTE]; 

                    break;
                }

            case FLD_LONG:
                 {
                    union {
                        long lnVar;
                        unsigned char lnVars[4];
                    } lnUn;

                    szCfgVal[11] = NULL_CH;
                    strcpy(szCnv, "%ld");               
                    sscanf(szCfgVal, szCnv, &lnTemp);
                    lnUn.lnVar = lnTemp;                    
                    pchRdBuf[inOffset] = lnUn.lnVars[LOBYTE]; 
                    pchRdBuf[inOffset + 1] = lnUn.lnVars[HIBYTE]; 
                    pchRdBuf[inOffset + 2] = lnUn.lnVars[LOBYTE2]; 
                    pchRdBuf[inOffset + 3] = lnUn.lnVars[HIBYTE2];

                    break;
                }

            case FLD_STR:
                 {
                    /* NULL_CH-terminated string */
                    strlcpy(((char *) pchRdBuf + inOffset), szCfgVal, (inTargetSize - 1));
                    break;
                }

            case FLD_BYTE:
                 {
                    /* numeric-only */
                    szCfgVal[4] = NULL_CH;
                    sscanf(szCfgVal, szCnv, &chTemp);
                    pchRdBuf[inOffset] = chTemp; 
                    break;
                }

            case FLD_BIT:
                 {
                    szCfgVal[1] = NULL_CH;
                    sscanf(szCfgVal, szCnv, &inTemp);
                    ucNewVal = (unsigned char) 1;

                    while ((inTestVal = (inTotFields - inStartBits)) >= 8) {
                        inStartBits += 8;
                    }

                    ucNewVal <<= (8 - ((inTotFields - inStartBits) + 1));

                    ucOldVal = pchRdBuf[inOffset];


                    if (inTemp)
                        ucNewVal |= ucOldVal;
                    else {
                        ucNewVal = (unsigned char) (~ucNewVal);
                        ucNewVal &= ucOldVal;
                    }

                    pchRdBuf[inOffset] = ucNewVal; 
                    break;
                }

            default:
                 {
                    close(hDataFile);
                    pdebug(("Bad Type2-%x", srFld.ucFieldType));
                    return(VS_ERR);
                }
            }

            if (lseek(hDataFile, (long) (-inRecSize), SEEK_CUR) < 0L) {
                /** /pdebug(("Bad Seek"));*/
                vdFree(pchRdBuf);
                close(hDataFile);
                return(VS_ERR);
            }

            if (write(hDataFile, pchRdBuf, inRecSize) != inRecSize) {
                /** /pdebug(("Bad Write"));*/
                vdFree(pchRdBuf);
                close(hDataFile);
                return(VS_ERR);
            }

            if (pchRdBuf)
                vdFree(pchRdBuf);
        }

        if (close(hDataFile) < 0) {
            /** /pdebug(("close hDataFile"));*/
            return(VS_ERR);
        }
    }

    return(VS_SUCCESS);
}

int inInitExpressConfig(TRANSACTION_OBJECT* pobTran) {
    if (fZtExprConfReqd() == VS_TRUE) {
        vdDisplayMessageFromFile(ZT_LOAD_MSG, STATUS_MSG);
        if (inGetExprCfg() != VS_SUCCESS) {
            vdSGErrorMessage(CFG_XPR_ERR);
            return(VS_ERR);
        }
    }

    if (inLoadHDTRec(0) != VS_SUCCESS) {
        vdSGErrorMessage(HDT_ERR_MSG21);
        return (VS_ERR);
    }

    if (inLoadTCTRec(0) != VS_SUCCESS) {
        vdSGErrorMessage(TCT_ERR_MSG21);
        return (VS_ERR);
    }

    if (inLoadPCTRec(0) != VS_SUCCESS) {
        vdSGErrorMessage(PCT_ERR_MSG);
        return (VS_ERR);
    }


    return (VS_SUCCESS);
}

#undef VSTZEXPR_C

#endif //#ifdef ZTEXPRESS_DEFINED
